from flask import request, current_app
from flask_restx import Resource, Namespace, fields
from flask_jwt_extended import create_access_token, get_jwt_identity, jwt_required
from app.services.user_service import UserService
from app.utils.validators import validate_required_fields, validate_phone
from app.utils.response import success_response, error_response
import random
import redis
import json
from . import api

# 创建命名空间
auth_ns = Namespace('auth', description='用户认证相关接口')

# 定义请求模型
wechat_login_model = auth_ns.model('WechatLogin', {
    'code': fields.String(required=True, description='微信登录code')
})

send_sms_model = auth_ns.model('SendSms', {
    'phone': fields.String(required=True, description='手机号')
})

verify_phone_model = auth_ns.model('VerifyPhone', {
    'phone': fields.String(required=True, description='手机号'),
    'code': fields.String(required=True, description='验证码')
})

@auth_ns.route('/wechat-login')
class WechatLoginAPI(Resource):
    """微信登录"""
    
    @auth_ns.expect(wechat_login_model)
    def post(self):
        # 验证必填字段
        is_valid, error_msg = validate_required_fields(['code'])
        if not is_valid:
            return error_response(error_msg, 400)
        
        data = request.get_json()
        code = data.get('code')
        
        try:
            # 调用用户服务处理微信登录（只传code）
            user_info, is_new = UserService.wechat_login(code)
            
            # 生成JWT Token（identity必须是字符串）
            access_token = create_access_token(identity=f"user_{user_info['id']}")
            
            return success_response({
                'token': access_token,
                'user_info': user_info,
                'is_new_user': is_new
            }, '登录成功')
        except Exception as e:
            current_app.logger.error(f"微信登录异常: {str(e)}")
            return error_response(f"微信登录失败: {str(e)}", 500)


@auth_ns.route('/send-sms')
class SendSmsAPI(Resource):
    """发送短信验证码"""
    
    @auth_ns.expect(send_sms_model)
    def post(self):
        # 验证必填字段
        is_valid, error_msg = validate_required_fields(['phone'])
        if not is_valid:
            return error_response(error_msg, 400)
        
        data = request.get_json()
        phone = data.get('phone')
        
        # 验证手机号格式
        if not validate_phone(phone):
            return error_response('手机号格式不正确', 400)
        
        try:
            # 生成随机验证码（6位数字）
            code = ''.join([str(random.randint(0, 9)) for _ in range(6)])
            
            # 连接Redis
            redis_client = redis.Redis.from_url(current_app.config['REDIS_URL'])
            
            # 检查是否有未过期的验证码
            phone_key = f"sms_code:{phone}"
            if redis_client.exists(phone_key):
                remaining_ttl = redis_client.ttl(phone_key)
                if remaining_ttl > 540:  # 9分钟以上，意味着发送未超过1分钟
                    return error_response('发送太频繁，请稍后再试', 400)
            
            # 保存验证码到Redis，有效期5分钟
            redis_client.setex(phone_key, 300, code)
            
            # 调用短信服务发送验证码（这里是模拟发送）
            if current_app.config['DEBUG']:
                print(f"DEBUG模式: 手机号 {phone} 的验证码是: {code}")
            else:
                # 真实环境下调用SMS服务发送验证码
                # 此处调用短信服务SDK发送验证码
                pass
            
            return success_response(message='验证码已发送')
        except Exception as e:
            current_app.logger.error(f"发送验证码异常: {str(e)}")
            return error_response(f"发送验证码失败: {str(e)}", 500)


@auth_ns.route('/verify-phone')
class VerifyPhoneAPI(Resource):
    """验证手机号"""
    
    @auth_ns.expect(verify_phone_model)
    @jwt_required()
    def post(self):
        # 验证必填字段
        is_valid, error_msg = validate_required_fields(['phone', 'code'])
        if not is_valid:
            return error_response(error_msg, 400)
        
        data = request.get_json()
        phone = data.get('phone')
        code = data.get('code')
        
        # 验证手机号格式
        if not validate_phone(phone):
            return error_response('手机号格式不正确', 400)
        
        try:
            # 从JWT中获取用户ID
            jwt_identity = get_jwt_identity()
            if not jwt_identity or not jwt_identity.startswith('user_'):
                return error_response('无效的认证信息', 401)
            
            user_id = int(jwt_identity.replace('user_', ''))
            
            # 连接Redis
            redis_client = redis.Redis.from_url(current_app.config['REDIS_URL'])
            
            # 检查验证码是否正确
            phone_key = f"sms_code:{phone}"
            stored_code = redis_client.get(phone_key)
            
            if not stored_code:
                return error_response('验证码已过期或不存在', 400)
            
            if stored_code.decode() != code:
                return error_response('验证码不正确', 400)
            
            # 验证通过，绑定手机号
            user = UserService.update_user_phone(user_id, phone)
            if not user:
                return error_response('用户不存在', 404)
            
            # 删除验证码
            redis_client.delete(phone_key)
            
            return success_response(user.to_dict(), '手机号验证成功')
        except Exception as e:
            current_app.logger.error(f"验证手机号异常: {str(e)}")
            return error_response(f"验证手机号失败: {str(e)}", 500)


@auth_ns.route('/logout')
class LogoutAPI(Resource):
    """用户登出"""
    
    @jwt_required()
    def post(self):
        # 由于使用JWT，服务器端无需特别处理登出逻辑
        # 客户端只需删除本地存储的token即可
        return success_response(message='登出成功')


@auth_ns.route('/refresh')
class RefreshTokenAPI(Resource):
    """刷新Token"""
    
    @jwt_required()
    def post(self):
        jwt_identity = get_jwt_identity()
        if not jwt_identity or not jwt_identity.startswith('user_'):
            return error_response('无效的认证信息', 401)
        
        # 生成新的access token
        new_access_token = create_access_token(identity=jwt_identity)
        
        return success_response({
            'token': new_access_token
        }, '刷新成功')


# 将命名空间注册到API实例
api.add_namespace(auth_ns) 